package top.codef.crypt.rsa;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

public class RSAPublicKeyPair {

	private RSAPublicKey rsaPublicKey;

	private String algorithm = "RSA";

	private String signAlgorithm = "MD5withRSA";

	public RSAPublicKeyPair(RSAPublicKey rsaPublicKey, SignAlgorithm signAlgorithm) {
		this.rsaPublicKey = rsaPublicKey;
		this.signAlgorithm = signAlgorithm.getSignType();
	}

	public RSAPublicKeyPair(RSAPublicKey rsaPublicKey) {
		this.rsaPublicKey = rsaPublicKey;
	}

	public RSAPublicKeyPair(RSAPublicKey rsaPublicKey, SignAlgorithm signAlgorithm, RsaAlgorithm rsaAlgorithm) {
		this.rsaPublicKey = rsaPublicKey;
		this.signAlgorithm = signAlgorithm.getSignType();
		this.algorithm = rsaAlgorithm.getValue();
	}

	public RSAPublicKeyPair(String publicKeyBase64) {
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyBase64));
		KeyFactory keyFactory;
		try {
			keyFactory = KeyFactory.getInstance(algorithm);
			this.rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(x509EncodedKeySpec);
		} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public RSAPublicKeyPair(String publicKeyBase64, String algorithm, String signAlgorithm) {
		this.algorithm = algorithm;
		this.signAlgorithm = signAlgorithm;
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyBase64));
		KeyFactory keyFactory;
		try {
			keyFactory = KeyFactory.getInstance(algorithm);
			this.rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(x509EncodedKeySpec);
		} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @return the algorithm
	 */
	public String getAlgorithm() {
		return algorithm;
	}

	/**
	 * @param algorithm the algorithm to set
	 */
	public void setAlgorithm(String algorithm) {
		this.algorithm = algorithm;
	}

	/**
	 * @return the signAlgorithm
	 */
	public String getSignAlgorithm() {
		return signAlgorithm;
	}

	/**
	 * @param signAlgorithm the signAlgorithm to set
	 */
	public void setSignAlgorithm(String signAlgorithm) {
		this.signAlgorithm = signAlgorithm;
	}

	public RSAPublicKey getRsaPublicKey() {
		return rsaPublicKey;
	}

	public void setRsaPublicKey(RSAPublicKey rsaPublicKey) {
		this.rsaPublicKey = rsaPublicKey;
	}

	public String getPublickeyBase64() {
		return Base64.encodeBase64String(rsaPublicKey.getEncoded());
	}

	public boolean verifyPublicKey(byte[] content, byte[] sign) {
		try {
			Signature signature = Signature.getInstance(signAlgorithm);
			signature.initVerify(rsaPublicKey);
			signature.update(content);
			return signature.verify(sign);
		} catch (Exception e) {
			System.err.println("验证错误");
			e.printStackTrace();
		}
		return false;
	}

	public byte[] encrypt(byte[] bs) {
		try {
			Cipher cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
			return cipher.doFinal(bs);
		} catch (Exception e) {
			System.err.println("加密异常");
			e.printStackTrace();
		}
		return null;
	}

	public byte[] decypt(byte[] bs) {
		try {
			Cipher cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.DECRYPT_MODE, rsaPublicKey);
			return cipher.doFinal(bs);
		} catch (Exception e) {
			System.err.println("解密异常");
			e.printStackTrace();
		}
		return null;
	}
}
